local FileSystem = Tubes.FileSystem
FileSystem._File = {}
local File = FileSystem._File
File.__index = File
setmetatable (File, Tubes.FileSystem._Base)

FileSystem.File = Tubes.MakeConstructor (File)

-- Networking
local StringPool = Tubes.StringPool (65536)
local ContentCallbacks = {}

function File:ctor (name)
	FileSystem._Base.ctor (self, name)
	
	self.Type = "Unknown File"
	self.Name = name or ""
	
	self.Contents = nil
end

function File:IsFolder ()
	return false
end

function File:Read (ply, callback)
	if not self:PlayerHasPermission (ply, "Read") then
		callback (nil, "Access Denied")
		return
	end
	if not self.Contents then
		local Path = self:GetFullPath ()
		if ContentCallbacks [Path] then
			ContentCallbacks [Path] [#ContentCallbacks [Path] + 1] = callback
		else
			Tubes.Networking.Send ("FileReadRequest", self:GetOwner  (), ply, Path, callback)
		end
	else
		callback (self.Contents)
	end
end

function File:SetContents (contents)
	self.Contents = contents
end

Tubes.Networking.RegisterReader ("FileReadData", function (netMessage)
	local Index = netMessage:UShort ()
	local Path = StringPool:LookupString (Index)
	local Allowed = netMessage:UChar ()
	local File = Tubes.FileSystem.GetRoot ():GetItem (Path)
	if Allowed then
		local Contents = netMessage:String ()
		File:SetContents (Contents)
		File:Read (ContentCallbacks [Path].Player, function (contents)
			for _, Callback in ipairs (ContentCallbacks [Path]) do
				Callback (contents)
			end
		end)
	else
		for _, Callback in ipairs (ContentCallbacks [Path]) do
			Callback (nil, "Access Denied")
		end
	end
	ContentCallbacks [Path] = nil
	StringPool:RemoveString (Path)
end)

Tubes.Networking.RegisterSender ("FileReadData", function (netMessage, path, contents)
	netMessage:UShort (StringPool:ComputeIndex (path))
	netMessage:UChar (contents and 1 or 0)
	netMessage:String (contents)
end)

Tubes.Networking.RegisterReader ("FileReadRequest", function (netMessage)
	local Path = netMessage:String ()
	ErrorNoHalt ("Received read request for " .. Path .. "\n")
	local File = Tubes.FileSystem.GetRoot ():GetItem (Path)
	if not File then
		return
	end
	local Source = netMessage:Player ()
	if SERVER then
		Source = netMessage:GetSource ()
	end
	File:Read (Source, function (contents)
		Tubes.Networking.Send ("FileReadData", netMessage:GetSource (), Path, contents)
	end)
end)

Tubes.Networking.RegisterSender ("FileReadRequest", function (netMessage, ply, path, callback)
	netMessage:String (path)
	netMessage:Player (ply)
	
	ContentCallbacks [path] = ContentCallbacks [path] or {Player = ply}
	ContentCallbacks [path] [#ContentCallbacks [path] + 1] = callback
	StringPool:AddString (path)
end)